﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Linq;

namespace UnityDefaultSetting.TextDefaultSetting.Editor
{
    /// <summary>
    /// 该默认设置脚本用于为文本组件设置默认字体、大小、对齐方式和颜色
    /// 适用于Text、Button、InputField、Dropdown等带有Text组件的组件
    /// 可以根据不同的组件加载不同的配置
    /// </summary>
    [InitializeOnLoad]
    public class TextDefaultFontSetter
    {
        private static List<Type> componentTypes = new List<Type>();
        private static List<Component> components = new List<Component>();

        public static TextDefaultTemplateConfig defaultSettingConfig;

        static TextDefaultFontSetter()
        {
            //订阅创建新对象时触发的事件
            ObjectFactory.componentWasAdded -= OnComponentWasAdded;
            ObjectFactory.componentWasAdded += OnComponentWasAdded;
        }

        private static void OnComponentWasAdded(Component component)
        {
            if (defaultSettingConfig == null)
                defaultSettingConfig = Resources.Load<TextDefaultTemplateConfig>("TextDefaultTemplateConfig");

            if (defaultSettingConfig.isEnable == false) return;

            if(!componentTypes.Contains(component.GetType()))
                componentTypes.Add(component.GetType());

            components.Add(component);

            if (ConditionComponentType(() => componentTypes.Contains(typeof(Button)) && componentTypes.Contains(typeof(Text)), () => {

                Component button = components.FirstOrDefault(item => item.GetType() == typeof(Button));

                //Debug.Log($"OnComponentWasAdded: {button}");

                SetButtonDefaultValueDelay(button);

                components.Clear();
                componentTypes.Clear();
            })) return;
            
            if (ConditionComponentType(() => componentTypes.Contains(typeof(Dropdown)) && componentTypes.Contains(typeof(Text)), () => {

                Component dropdown = components.FirstOrDefault(item => item.GetType() == typeof(Dropdown));

                //Debug.Log($"OnComponentWasAdded: {dropdown}");

                SetDropdownDefaultValueDelay(dropdown);

                components.Clear();
                componentTypes.Clear();

            })) return;

            if (ConditionComponentType(() => componentTypes.Contains(typeof(InputField)) && componentTypes.Contains(typeof(Text)), () => {
                Component inputField = components.FirstOrDefault(item => item.GetType() == typeof(InputField));

                //Debug.Log($"OnComponentWasAdded: {inputField}");

                SetInputFieldDefaultValueDelay(inputField);

                components.Clear();
                componentTypes.Clear();
            })) return;


            if (ConditionComponentType(() => componentTypes.Contains(typeof(Text)), () => {
                //Debug.Log($"OnComponentWasAdded: {component}");

                SetTextDefaultValueDelay(component as Text);

                components.Clear();
                componentTypes.Clear();
            })) return;
        }

        private static bool ConditionComponentType(Func<bool> predicate,Action action = null)
        {
            if (predicate.Invoke())
            {
                ObjectFactory.componentWasAdded -= OnComponentWasAdded;

                EditorApplication.delayCall += OnDelayCall;

                void OnDelayCall()
                {
                    action?.Invoke();
                    EditorApplication.delayCall -= OnDelayCall;
                    ObjectFactory.componentWasAdded += OnComponentWasAdded;
                }
                return true;
            }
            return false;
        }

        private static void SetTextDefaultValueDelay(Component component)
        {
            TextDefaultSettingConfig textConfig = defaultSettingConfig.textConfig;// Resources.Load<TextDefaultSettingConfig>("TextConfig/TextDefaultSettingConfig");
            SetDefaultValueDelay((Text)component, textConfig);
        }

        private static void SetButtonDefaultValueDelay(Component component)
        {
            TextDefaultSettingConfig buttonConfig = defaultSettingConfig.buttonTextConfig;// Resources.Load<TextDefaultSettingConfig>("TextConfig/ButtonTextDefaultSettingConfig");
            Text text = component.GetComponentInChildren<Text>();

            SetDefaultValueDelay(text, buttonConfig);
        }

        private static void SetDropdownDefaultValueDelay(Component component)
        {
            TextDefaultSettingConfig dropDownItemTextConfig = defaultSettingConfig.dropDownItemLabelConfig;// Resources.Load<TextDefaultSettingConfig>("TextConfig/DropDownItemLabelDefaultSettingConfig");
            TextDefaultSettingConfig dropDownLabelTextConfig = defaultSettingConfig.dropDownLabelConfig;// Resources.Load<TextDefaultSettingConfig>("TextConfig/DropDownLabelDefaultSettingConfig");

            Dropdown dropdown = component as Dropdown;

            SetDefaultValueDelay(dropdown.captionText, dropDownLabelTextConfig);

            SetDefaultValueDelay(dropdown.itemText, dropDownItemTextConfig);
        }

        private static void SetInputFieldDefaultValueDelay(Component component)
        {
            TextDefaultSettingConfig inputFieldPlaceholderConfig = defaultSettingConfig.inputFieldPlaceholderConfig;// Resources.Load<TextDefaultSettingConfig>("TextConfig/InputFieldPlaceholderDefaultSettingConfig");
            TextDefaultSettingConfig inputFieldTextConfig = defaultSettingConfig.inputFieldTextConfig;// Resources.Load<TextDefaultSettingConfig>("TextConfig/InputFieldTextDefaultSettingConfig");


            InputField inputField = component as InputField;

            SetDefaultValueDelay(inputField.textComponent, inputFieldTextConfig);

            SetDefaultValueDelay((Text)inputField.placeholder, inputFieldPlaceholderConfig);
        }


        private static void SetDefaultValueDelay(Text textComponent, TextDefaultSettingConfig settingConfig)
        {
            // 确保颜色设置在所有其他设置之后
            EditorApplication.delayCall += OnDelayCall;

            void OnDelayCall()
            {
                SetDefaultFont(textComponent, settingConfig);
                SetDefaultSize(textComponent, settingConfig);
                SetDefaultAlignment(textComponent, settingConfig);
                SetDefaultColor(textComponent, settingConfig);

                EditorApplication.delayCall -= OnDelayCall;
            }
        }

        private static void SetDefaultFont(Text textComponent, TextDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            //将文本组件的字体设置为自定义默认字体
            if (settingConfig == null || settingConfig.defaultFont == null)
            {
                textComponent.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
                Debug.LogWarning("自定义字体为空，请检查配置文件是否正确。使用默认Arial字体。");
            }
            else
            {
                textComponent.font = settingConfig.defaultFont;
            }

            EditorUtility.SetDirty(textComponent);
        }

        private static void SetDefaultColor(Text textComponent, TextDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            textComponent.color = settingConfig.defaultFontColor;
            EditorUtility.SetDirty(textComponent);
        }

        private static void SetDefaultSize(Text textComponent, TextDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            textComponent.fontSize = settingConfig.defaultFontSize;
            EditorUtility.SetDirty(textComponent);
        }

        private static void SetDefaultAlignment(Text textComponent, TextDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            textComponent.alignment = settingConfig.defaultAlignment;
            EditorUtility.SetDirty(textComponent);
        }

        private static void DelayAction(Text textComponent, float delay, System.Action<Text> action)
        {
            float startTime = (float)EditorApplication.timeSinceStartup;
            EditorApplication.update += OnUpdateCall;

            void OnUpdateCall()
            {
                if ((float)EditorApplication.timeSinceStartup - startTime >= delay)
                {
                    EditorApplication.update -= OnUpdateCall;
                    action?.Invoke(textComponent);
                }
            }
        }
    }
}
